package com.log.james.controller;

import com.log.james.entity.R;
import com.log.james.entity.SecurityEvent;
import com.log.james.entity.SecurityLog;
import com.log.james.entity.WebFlow;
import com.log.james.service.AbnormalService;
import com.log.james.service.FwlogService;
import com.log.james.service.WebLogAttackService;
import com.log.james.utils.IPChangeUtil;
import com.log.james.utils.JsonUtil;
import com.log.james.utils.ListMapUtil;
import com.log.james.utils.ProtocolUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 事件控制器
 */

@RestController
@Api(tags = "事件接口")
public class EventController {

    private JsonUtil jsonUtil = new JsonUtil();
    private IPChangeUtil ipChangeUtil = new IPChangeUtil();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private ProtocolUtil protocolUtil = new ProtocolUtil();
    private ListMapUtil listMapUtil = new ListMapUtil();
//    若是两个类型相似的事件发生的时间间隔小于5s，则认为是一个攻击事件
    private final int TIME_INTERVAL = 5000;

    @Autowired
    private WebLogAttackService webLogAttackService;
    @Autowired
    private AbnormalService abnormalService;

    @Autowired
    private FwlogService fwlogService;


    @PostMapping("/eventDetail")
    @ResponseBody
    @ApiOperation("事件详情接口")
    public String eventDetail(HttpServletRequest request, HttpServletResponse response){
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain");

        String time = request.getParameter("time");
        Date happenTime = new Date();
        Map<String,Object> eventDetailResponseData = new HashMap<>();

        String description = "";
        List<SecurityLog> securityLogs = new LinkedList<>();
//        事件类型
        try{
            happenTime = sdf.parse(time);
        }catch (ParseException e){
            e.printStackTrace();
        }

        String type = request.getParameter("type");
//        特征
        String feature = request.getParameter("feature");

//        攻击
        if(type.equals("attack")){
            List<Map<String,Object>> attacks = webLogAttackService.findAttackByStartTime(happenTime);
            if (attacks.size() == 0){
                securityLogs.add(null);
            }else{
                for (Map<String,Object> map : attacks){
                    String startTime = String.valueOf(map.get("starttime"));
                    String attackType = "web";
                    String ip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(map.get("srcip"))));

                    Map<String,Object> map1 = new HashMap<>();
                    map1.put("url",String.valueOf(map.get("url")));

                    description = String.valueOf(map.get("advice"));
                    SecurityLog securityLog = new SecurityLog(startTime,attackType,ip,null,null,null,map1);
                    securityLogs.add(securityLog);
                }
            }
        }else{
//            web流量异常
            if(type.equals("streamAbnormal") && feature.equals("web")){

            }else{
                if (type.equals("visitorAbnormal")){
                    long srcip = ipChangeUtil.ipStrToLong(feature);
                    List<Map<String,Object>> fwlogs = fwlogService.findFwlogByTimeAndSrcIP(happenTime,srcip);
                    if (fwlogs.size() == 0){
                        securityLogs.add(null);
                    }else{
                        for (Map<String,Object> fwlog:fwlogs){
                            String srcport = String.valueOf(fwlog.get("srcport"));
                            String destip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(fwlog.get("destip"))));
                            String destport = String.valueOf(fwlog.get("destport"));

                            Map<String,String> map = new HashMap<>();
                            String protocol = protocolUtil.protocol().get(Integer.parseInt(destport));
                            map.put("protocol",protocol);

                            SecurityLog securityLog = new SecurityLog(time,"firewall",feature,srcport,destip,destport,map);
                            securityLogs.add(securityLog);
                        }
                    }

                }
                else if (type.equals("portAbnormal")){
                    int destport = Integer.parseInt(feature);
                    List<Map<String,Object>> fwlogs = fwlogService.findFwlogByTimeAndDestPort(happenTime,destport);
                    if (fwlogs.size() == 0){
                        securityLogs.add(null);
                    }else{
                        for (Map<String,Object> fwlog:fwlogs){
                            String srcip = String.valueOf(fwlog.get("srcip"));
                            String srcport = String.valueOf(fwlog.get("srcport"));
                            String destip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(fwlog.get("destip"))));

                            Map<String,Object> map = new HashMap<>();
                            String protocol = protocolUtil.protocol().get(Integer.parseInt(feature));
                            map.put("protocol",protocol);

                            SecurityLog securityLog = new SecurityLog(time,"firewall",srcip,srcport,destip,feature,map);
                            securityLogs.add(securityLog);
                        }
                    }

                }
                else if (type.equals("ipAbnormal")){
                    long destip = ipChangeUtil.ipStrToLong(feature);
                    List<Map<String,Object>> fwlogs = fwlogService.findFwlogByTimeAndDestIP(happenTime,destip);
                    if (fwlogs.size() == 0){
                        securityLogs.add(null);
                    }else{
                        for (Map<String,Object>fwlog:fwlogs){
                            String srcip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(fwlog.get("srcip"))));
                            String srcport = String.valueOf(fwlog.get("srcport"));
                            String destport = String.valueOf(fwlog.get("destport"));

                            Map<String,Object> map = new HashMap<>();
                            String protocol = protocolUtil.protocol().get(Integer.parseInt(destport));
                            map.put("protocol",protocol);

                            SecurityLog securityLog = new SecurityLog(time,"firewall",srcip,srcport,feature,destport,map);
                            securityLogs.add(securityLog);
                        }
                    }

                }
            }
        }

        eventDetailResponseData.put("description",description);
        eventDetailResponseData.put("data",securityLogs);

        return jsonUtil.mapToJson(eventDetailResponseData);
    }

    @PostMapping("/events")
    @ResponseBody
    @ApiOperation("事件接口")
    public R event(Long startT,Long endT,String type,String subType,int limitSize,int isDesc){
        String startTime = sdf.format(new Date(startT));
        String endTime = sdf.format(new Date(endT));
        Date st = new Date();
        Date et = new Date();
        try{
            st = sdf.parse(startTime);
            et = sdf.parse(endTime);
        }catch (ParseException e){
            e.printStackTrace();
        }

//    }
//    public String event(HttpServletResponse response,HttpServletRequest request){
//        response.setContentType("text/plain;charset=utf-8");
//        Date startT = new Date(Long.parseLong(request.getParameter("startTime")));
//        Date endT = new Date(Long.parseLong(request.getParameter("endTime")));
//
//        String startTime = sdf.format(startT);
//        String endTime = sdf.format(endT);
////        类型，异常行为，攻击事件
//        String type = request.getParameter("type");
//        String subType = request.getParameter("subType");
//        int limitSize = Integer.parseInt(request.getParameter("limitSize"));
//        int isDesc = Integer.parseInt(request.getParameter("isDesc"));
//        Date st = new Date();Date et = new Date();
//        try{
//            st = sdf.parse(startTime);
//            et = sdf.parse(endTime);
//        }catch (Exception e){
//            e.printStackTrace();
//        }

        List<SecurityEvent> securityEvents = new LinkedList<>();
//        攻击
        if (type.equals("attack")){
            //获取web攻击事件
//            判断limitSize,正数为返回的最大数量，负数为全部
            List<Map<String,Object>> webAttacks = new LinkedList<>();
//            返回的数据是按照开始时间进行排序的
            if (limitSize > 0){
                webAttacks = webLogAttackService.findPartMessageByTime(st,et,subType,limitSize);
            }else{
                webAttacks = webLogAttackService.findAllMessageByTime(st,et,subType);
            }
            if (webAttacks.size() == 1){
                String beginTime = String.valueOf(webAttacks.get(0).get("starttime"));
                String finishTime = String.valueOf(webAttacks.get(0).get("endtime"));

                Map<String,Object> map = new HashMap<>();
                if (subType.equals("DDos攻击")){
                    map.put("type",subType);
                    map.put("srcIp","");
                    map.put("srcCity","");
                    SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,map);
                    securityEvents.add(securityEvent);
                }else{
                    String ip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(webAttacks.get(0).get("srcip"))));
                    String address = String.valueOf(webAttacks.get(0).get("address"));
                    if (address.equals("域外")){
                        address = "";
                    }
                    map.put("type",startTime);
                    map.put("srcIp",ip);
                    map.put("srcCity",address);
                    SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,map);
                    securityEvents.add(securityEvent);
                }
            }
            else if (webAttacks.size() > 1){
                String beginTime = String.valueOf(webAttacks.get(0).get("starttime"));
                String finishTime = String.valueOf(webAttacks.get(0).get("endtime"));
                try{
                    for (int i = 0 ; i < webAttacks.size() ; i++){
                        if (i == webAttacks.size() - 1){
                            if (sdf.parse(String.valueOf(webAttacks.get(i).get("starttime"))).getTime() - sdf.parse(String.valueOf(webAttacks.get(i - 1).get("endtime"))).getTime() > TIME_INTERVAL){
                                Map<String,Object> map = new HashMap<>();
                                String ip = "";
                                String address = "";
                                if (subType.equals("DDos攻击")){
                                    ip="";
                                    address = "";
                                }else{
                                    ip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(webAttacks.get(i).get("srcip"))));
                                    address = (String)webAttacks.get(i).get("address");
                                    if (address.equals("域外")){
                                        address="";
                                    }
                                }
                                map.put("type",subType);
                                map.put("srcIp",ip);
                                map.put("srcCity",address);

                                SecurityEvent securityEvent = new SecurityEvent(String.valueOf(webAttacks.get(i).get("starttime")),
                                        String.valueOf(webAttacks.get(i).get("endtime")),type,map);
                                securityEvents.add(securityEvent);

                            }else{
                                String ip = "";
                                String address = "";
                                if (subType.equals("DDos攻击")){
                                    ip="";
                                    address="";
                                }else{
                                    ip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(webAttacks.get(i).get("srcip"))));
                                    address = (String)webAttacks.get(i).get("address");
                                    if (address.equals("域外")){
                                        address="";
                                    }
                                }
                                Map<String,Object> map = new HashMap<>();
                                map.put("type",subType);
                                map.put("srcIp",ip);
                                map.put("srcCity",address);

                                SecurityEvent securityEvent = new SecurityEvent(startTime,
                                        String.valueOf(webAttacks.get(i).get("endtime")),type,map);
                                securityEvents.add(securityEvent);
                            }
                        }else{
                            if (sdf.parse(String.valueOf(webAttacks.get(i + 1).get("starttime"))).getTime()
                                    - sdf.parse(String.valueOf(webAttacks.get(i).get("endtime"))).getTime() > TIME_INTERVAL){
                                finishTime = String.valueOf(webAttacks.get(i).get("endtime"));

                                Map<String,Object> map = new HashMap<>();
                                String ip = "";
                                String address = "";
                                if (subType.equals("DDos攻击")){
                                    ip = "";
                                    address = "";
                                }else{
                                    ip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(webAttacks.get(i).get("srcip"))));
                                    address = (String)webAttacks.get(i).get("address");
                                    if (address.equals("域外")){
                                        address = "";
                                    }
                                }
                                map.put("type",subType);
                                map.put("srcIp",ip);
                                map.put("srcCity",address);
                                SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,map);
                                beginTime = finishTime;
                                securityEvents.add(securityEvent);
                            }
                        }
                    }
                }catch (ParseException e){
                    e.printStackTrace();
                }
            }
            else{
                securityEvents.add(null);
            }
        }
//        目的IP访问异常
        else if (type.equals("ipAbnormal")){
            List<Map<String,Object>> ipAbnormals = new LinkedList<>();
            if (limitSize > 0){
                ipAbnormals = abnormalService.findIpAbnormal(st,et,limitSize);
            }else{
                ipAbnormals = abnormalService.findAllIpAbnormal(st,et);
            }
            if (ipAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> ipAbnormal:ipAbnormals){
                    SecurityEvent securityEvent = getIPAbnormal(ipAbnormal,type);
                    securityEvents.add(securityEvent);
                }
            }

        }
//        端口异常
        else if (type.equals("portAbnormal")){
            List<Map<String,Object>> portAbnormals = new LinkedList<>();
            if (limitSize > 0){
                portAbnormals = abnormalService.findPortAbnormal(st,et,limitSize);
            }else{
                portAbnormals = abnormalService.findAllPortAbnormal(st,et);
            }
            if (portAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> portAbnormal:portAbnormals){
                    SecurityEvent securityEvent = getPortAbnormal(portAbnormal,type);
                    securityEvents.add(securityEvent);
                }
            }

        }else if (type.equals("streamAbnormal")){
//            防火墙流量异常
            if (subType.equals("firewall")){
                List<Map<String,Object>> fwStreamAbnormals = new LinkedList<>();
                if (limitSize > 0){
                    fwStreamAbnormals = abnormalService.findFireWallStreamAbnormal(st,et,limitSize);
                }else{
                    fwStreamAbnormals = abnormalService.findAllFireWallStreamAbnormal(st,et);
                }
                List<SecurityEvent> streamSecurityEvents = getBothStream(fwStreamAbnormals,type,subType);
                securityEvents.addAll(streamSecurityEvents);
            }
//            web流量异常
            else{
                List<Map<String,Object>> webAbnormals = new LinkedList<>();
                if (limitSize > 0){
                    webAbnormals = abnormalService.findWebStreamAbnormal(st,et,limitSize);
                }else{
                    webAbnormals = abnormalService.findAllWebStreamAbnormal(st,et);
                }
                List<SecurityEvent> streamSecurityEvents = getBothStream(webAbnormals,type,subType);
                securityEvents.addAll(streamSecurityEvents);
            }
        }
        else if (type.equals("visitorAbnormal")){
            List<Map<String,Object>> visitorAbnormals = new LinkedList<>();
            if (limitSize > 0){
                visitorAbnormals = abnormalService.findVisitorAbnormal(st,et,limitSize);
            }else{
                visitorAbnormals = abnormalService.findAllVisitorAbnormal(st,et);
            }
            if (visitorAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> map : visitorAbnormals){
                    SecurityEvent securityEvent = getVisitorAbnormal(map,type);
                    securityEvents.add(securityEvent);
                }
            }

        }else if(type.equals("allAbnormal")){
//            获取所有的异常内容
//            ipAbnormal
            List<Map<String,Object>> ipAbnormals = abnormalService.findAllIpAbnormal(st,et);
            if (ipAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> ipAbnormal:ipAbnormals){
                    SecurityEvent securityEvent = getIPAbnormal(ipAbnormal,type);
                    securityEvents.add(securityEvent);
                }
            }

//            portAbnormal
            List<Map<String,Object>> portAbnormals = abnormalService.findAllPortAbnormal(st,et);
            if (portAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> portAbnormal:portAbnormals){
                    SecurityEvent securityEvent = getPortAbnormal(portAbnormal,type);
                    securityEvents.add(securityEvent);
                }
            }

//            streamAbnormal
            List<Map<String,Object>> fireWallStreamAbnormals = abnormalService.findAllFireWallStreamAbnormal(st,et);
            List<SecurityEvent> fireWallStreamSecurity = getBothStream(fireWallStreamAbnormals,type,subType);
            securityEvents.addAll(fireWallStreamSecurity);


            List<Map<String,Object>> webStreamAbnormals = abnormalService.findAllWebStreamAbnormal(st,et);
            List<SecurityEvent> webStreamSecurity = getBothStream(webStreamAbnormals,type,subType);
            securityEvents.addAll(webStreamSecurity);


//            visitorAbnormal
            List<Map<String,Object>> visitorAbnormals = abnormalService.findAllVisitorAbnormal(st,et);
            if (visitorAbnormals.size() == 0){
                securityEvents.add(null);
            }else{
                for (Map<String,Object> visitorAbnormal:visitorAbnormals){
                    SecurityEvent securityEvent = getVisitorAbnormal(visitorAbnormal,type);
                    securityEvents.add(securityEvent);
                }
            }

//            对于上述内容的处理
            //按照时间进行排序
            listMapUtil.makeEntityListMap(securityEvents,"startTime");
            if (limitSize > 0)
                securityEvents = securityEvents.subList(0,limitSize);
        }

        Map<String,Object> eventsResponseData = new HashMap<>();
        eventsResponseData.put("startTime",startTime);
        eventsResponseData.put("endTime",endTime);
        eventsResponseData.put("events",securityEvents);

//        return jsonUtil.mapToJson(eventsResponseData);
        return R.ok().put("data",eventsResponseData);
    }

    /**
     * ip异常事件处理函数
     * @param ipMap
     * @param type
     * @return
     */
    private SecurityEvent getIPAbnormal(Map<String,Object> ipMap,String type){
        String beginTime = String.valueOf(ipMap.get("starttime"));
        String finishTime = String.valueOf(ipMap.get("endtime"));

        Map<String,Object> maps = new HashMap<>();
        maps.put("destIp",ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(ipMap.get("destip")))));
        maps.put("value",Integer.parseInt(String.valueOf(ipMap.get("sum"))));

        SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,maps);
        return securityEvent;
    }

    /**
     * 端口异常事件
     * @param portMap
     * @param type
     * @return
     */
    private SecurityEvent getPortAbnormal(Map<String,Object> portMap,String type){
        String beginTime = String.valueOf(portMap.get("starttime"));
        String finishTime = String.valueOf(portMap.get("endtime"));

        Map<String,Object> maps = new HashMap<>();
        maps.put("dstPort",String.valueOf(portMap.get("destports")));
        maps.put("destIp",ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(portMap.get("destip")))));
        maps.put("value",Integer.parseInt(String.valueOf(portMap.get("counts"))));

        SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,maps);
        return securityEvent;
    }

    /**
     *
     * 流量事件处理函数
     * @param streamMap
     * @param subType
     * @param type
     * @return
     */
    private SecurityEvent getStreamAbnormal(Map<String,Object> streamMap,String subType,String type){
        String beginTime = String.valueOf(streamMap.get("starttime"));
        String finishTime = String.valueOf(streamMap.get("endtime"));

        Map<String,Object> map = new HashMap<>();
        map.put("type",subType);
        map.put("value",Integer.parseInt(String.valueOf(streamMap.get("curstream"))));

        SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,map);
        return securityEvent;
    }

    /**
     * 访客异常
     * @param visitorAbnormal
     * @param type
     * @return
     */
    private SecurityEvent getVisitorAbnormal(Map<String,Object> visitorAbnormal,String type){
        String beginTime = String.valueOf(visitorAbnormal.get("starttime"));
        String finishTime = String.valueOf(visitorAbnormal.get("endtime"));
        Map<String,Object> maps = new HashMap<>();
        String destip = ipChangeUtil.ipLongToStr(Long.parseLong(String.valueOf(visitorAbnormal.get("srcip"))));
        String city = String.valueOf(visitorAbnormal.get("attackaddress"));
        int value = Integer.parseInt(String.valueOf(visitorAbnormal.get("sum")));
        maps.put("destIp",destip);
        maps.put("srcCity",city);
        maps.put("value",value);
        SecurityEvent securityEvent = new SecurityEvent(beginTime,finishTime,type,maps);
        return securityEvent;
    }

    /**
     * 流量链表处理函数
     * @param streamList
     * @param type
     * @param subType
     * @return
     */
    private List<SecurityEvent> getBothStream(List<Map<String,Object>> streamList,String type,String subType){
        List<SecurityEvent> securityEvents = new LinkedList<>();
        if (streamList.size() == 0){
            securityEvents.add(null);
        }else{
            for (Map<String,Object> stream:streamList){
                SecurityEvent securityEvent = getStreamAbnormal(stream,subType,type);
                securityEvents.add(securityEvent);
            }
        }
        return securityEvents;
    }


}
